#pragma once
#include "Common.hpp"
#include "InetAddr.hpp"
#include "Socket.hpp"
#include "functional"

using namespace SocketModule;

//客户端的请求  1.客户端需要序列化     2.服务端需要反序列化
class Request
{
public:
    Request(){}
    Request(int x, int y, char oper)
        :_x(x),
        _y(y),
        _oper(oper)
    {}

    // 客户端序列化 将数据传到网络 
    std::string Serialize()
    {
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root['oper'] = _oper;
        
        Json::FastWriter writer;
        std::string s = writer.write(root);
        return s;        
    }
    
    // 服务端反序列化
    bool Deserialize(std::string& in)
    {
        Json::Value root;
        Json::Reader reader;
        bool ok = reader.parse(in,root);
        if(ok)
        {
            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _oper = root["oper"].asInt();
        }
        return ok;
    }
   
    int X(){ return _x;}
    int Y(){ return _y;}
    char Oper(){ return _oper;}

private:
    int _x;
    int _y;
    char _oper;
};


//服务端回应   1.服务端需要序列化     2.客户端需要反序列化  
class Response
{
public:
    Response(){}
    Response(int result, int code)
        :_result(result),
        _code(code)
    {}


    std::string Serialize()
    {
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;
        Json::FastWriter writer;
        return writer.write(root);
    }

    void SetResult(int result) {  _result = result;}
    void SetCode(int code) {     _code = code; }
    void Set(int result,int code)
    {
        _result = result;
        _code = code;
    }

private:
    int _result;
    int _code;
};


const std::string seq = "/r/n";
using func_t = std::function<Response(Request& )>;

class Protocol
{
public:
    Protocol(func_t fun)
        :_func(fun)
    {
    }

    bool Decode(std::string& message, std::string* out)
    {
        size_t pos = message.find(seq);
        if(pos == std::string::npos)
        {
            return false;
        }
        std::string len = message.substr(0,pos);//数据长度的字符串
        size_t Data_len = std::stoi(len); //字符串转整型

        size_t total = sizeof(len) + Data_len + 2*sizeof(seq);//协议总长度

        if(message.size() < total) //如果当前消息的长度小于规定协议长度，说明不是一条完整的消息
            return false;

        //到这说明message内存在一条完整的消息
        *out = message.substr(pos+2,Data_len);
        message.erase(0,total);
        return true;
    }

    std::string Encode(std::string& in)
    {
        size_t len = sizeof(in);
        return std::to_string(len) + seq + in + seq;
    }

    void GetData(std::shared_ptr<Socket>& sockfd, InetAddr& client)
    {
        std::string message;
        while(true)
        {
            int n = sockfd->Recv(&message);
            if(n > 0)
            {
                //判断数据是否完整   规定协议为： 有效数据长度 + /r/n + 有效数据 + /r/n
                //1.解密
                std::string Package;
                if(!Decode(message,&Package))
                {
                    continue;
                }

                //2.将有效数据反序列化
                Request req;
                req.Deserialize(Package);

                //3.业务处理  处理的时候返回一个 response
                Response res = _func(req);

                //4.服务端将结果序列化
                std::string send_str = res.Serialize();
                //5. 加密

                std::string package = Encode(send_str);

                //6. 传给客户端
                sockfd->Send(package);
            }
            else if(n == 0)
            {
                LOG(LogLevel::INFO) << "客户端退出了";
                break;
            }
            else
            {
                LOG(LogLevel::WARNING) << "recv error";
                break;
            }
        }
    }
private:
    func_t _func;
};